﻿#define _CRT_SECURE_NO_WARNINGS                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
/*********************23.文件操作***********************/
#include <stdio.h>
//在程序设计中，我们⼀般谈的⽂件有两种：程序⽂件、数据⽂件
//int main()
//{
//	int a = 10000;
//	//fopen打开文件
//	FILE* pf = fopen("test.txt", "wb");//write binary写二进制
//	fwrite(&a, 4, 1, pf);//⼆进制的形式写到⽂件中
//	//地址，字节，次数，管理目标
//	fclose(pf);//关闭
//	pf = NULL;
//
//	return 0;
//
//}

/*主要处理数据文件*/
//根据数据的组织形式，数据⽂件被称为⽂本⽂件和⼆进制⽂件

/******1.文件的打开和关闭********/
/*流和标准流*/
/*流*/
//流：我们程序的数据需要输出到各种外部设备，也需要从外部设备获取数据，不同的外部设备的输⼊输出
//操作各不相同，为了⽅便程序员对各种设备进⾏⽅便的操作，我们抽象出了流的概念，

/*C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。*/

/*标准流*/
//默认打开三个流
//stdin - 标准输⼊流，在⼤多数的环境中从键盘输⼊，scanf函数就是从标准输⼊流中读取数据。
//stdout - 标准输出流，⼤多数的环境中输出⾄显⽰器界⾯，printf函数就是将信息输出到标准输出流中。
//stderr - 标准错误流，⼤多数环境中输出到显⽰器界⾯

/*stdin、stdout、stderr 三个流的类型是： FILE * ，通常称为⽂件指针。*/
/*读写文件*/
//(1).打开文件相关流
//(2).读/写文件
//(3).关闭文件流

/*文件指针*/
/*每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区，⽤来存放⽂件的相关信息（如⽂件的名
字，⽂件状态及⽂件当前的位置等）。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系
统声明的，取名 FILE*/

/*文件的打开和关闭*/
//使⽤ fopen 函数来打开⽂件， fclose 来关闭⽂件。
//int main()
//{
//	//FILE* pf = fopen("data.txt", "w");
//	 
//	//绝对路径
//	//FILE* pf = fopen("C:\\Users\\12936\\Desktop\\data.txt", "w");
//
//	//相对路径
//	//. 当前路径
//	//.. 上一级路径
//	FILE* pf = fopen("./../../data.txt", "w");
//
//	//按照指定路径写/读文件
//	
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;}
//	//读文件
//	
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

/***2.⽂件的顺序读写***/
/*顺序读写函数*/
//(1).fputc函数
//int main()
//{
//	FILE* pf = fopen("data.txt", "w");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//写文件
//	/*fputc('a',pf);
//	fputc('b', pf);
//	fputc('c', pf);*/
//
//	int i = 0;
//	for (i = 'a'; i <= 'z'; i++)
//	{
//		fputc(i,pf);
//	}
//
//	//关闭文件
//	fclose(pf);
//	pf == NULL;
//	return 0;
//}

//(2).fgetc函数
//int main()
//{
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	/*int ch = fgetc(pf);
//	printf("%c",ch);*/

/*从文件读*/
//	int ch = 0;
//	while ((ch = fgetc(pf)) != EOF)
//	{
//		//printf("%c ",ch);
//		putchar(ch);
//	}
//		
//
//	//关闭文件
//	fclose(pf);
//	pf == NULL;
//	return 0;
//}

/*从标准输入流读数据*/
//int main()
//{
//	int ch = fgetc(stdin);
//	putchar(ch);
//	fputc(ch,stdout);
//	return 0;
//}

//fputs函数
//int main()
//{
//	FILE* pf = fopen("data.txt","w");
//	//以写方式打开文件
//	//文件不存在会新建文件
//	//如果存在文件会清空文件原来内容
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//写文件
//	//fputs("i like c",pf);
//	//fputs("hello", pf);//写在同一行
//
//	fputs("i like c\n", pf);
//	fputs("hello\n", pf);
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//fgets函数
//int main()
//{
//	FILE* pf = fopen("data.txt", "r");
//	//以写方式打开文件
//	//文件不存在会新建文件
//	//如果存在文件会清空文件原来内容
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	char arr[20];
//	fgets(arr, 20, pf);//包含一个‘/0’
//	printf("%s",arr);
//
//	fgets(arr, 20, pf);//只能读一行，需要多次读行
//	printf("%s", arr);
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

/*从标准输入流读数据*/
//int main()
//{
//	//读文件
//	char arr[20];
//	fgets(arr, 20, stdin);//包含一个‘/0’
//	printf("%s", arr);
//	fputs(arr,stdin);
//
//	return 0;
//}

//fprintf函数,带可变参数
//int main()
//{
//	char name[20] = "zhangsan";
//	int age = 20;
//	double math = 95.5;
//
//	FILE* pf = fopen("data.txt", "w");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//写文件
//	fprintf(pf,"%s %d %.1lf",name, age, math);
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//fscanf函数
//struct S
//{
//	char name[20];
//	int age;
//	double math;
//};
//
//int main()
//{
//	/*char name[20] = "";
//	int age = 0;
//	double math = 0;*/
//
//	struct S s = { 0 };
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.math));
//	printf("%s %d %lf", s.name, s.age, s.math);
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//fread函数
//int main()
//{
//	FILE* pf = fopen("data.txt", "wb");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//写文件
//	//以二进制写
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	fwrite(arr,sizeof(int),10,pf);
//
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//fread函数
//int main()
//{
//	FILE* pf = fopen("data.txt", "rb");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	//以二进制读
//	int arr[10] = { 0 };
//	fread(arr, sizeof(int), 10, pf);
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//对⽐⼀组函数：
//scanf / fscanf / sscanf
//printf / fprintf / sprintf
/*sprintf将带有格式的数据，按照格式转换成字符串*/
/*sscanf从字符串中按照格式提取格式化的数据*/
//int main()
//{
//	char name[20] = "hua";
//	int age = 20;
//	double math = 90;
//
//	char buf[120] = { 0 };
//	sprintf(buf,"%s %d %.1lf", name, age, math);
//
//	printf("%s\n", buf);//字符串打印
//
//	char name2[20] = "";
//	int age2 = 0;
//	double math2 = 0;
//	//从buf按照格式提取数据到变量中
//	sscanf(buf, "%s %d %lf", name2, &age2, &math2);
//	printf("%s\n%d\n%.1lf\n", name2, age2, math2);
//
//	return 0;
//}

/*****3.⽂件的随机读写*****/
//fseek函数根据⽂件指针的位置和偏移量来定位⽂件指针
//ftell函数返回⽂件指针相对于起始位置的偏移量
//int main()
//{
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	int ch = fgetc(pf);
//	printf("%c\n",ch);//a
//
//	//fseek(pf,4,SEEK_SET);//e
//	//fseek(pf, 3, SEEK_CUR);//e
//	fseek(pf, -5, SEEK_END);//e
//
//	ch = fgetc(pf);
//	printf("%c\n", ch);
//
//	printf("%ld\n", ftell(pf));//5
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//rewind函数让⽂件指针的位置回到⽂件的起始位置
//int main()
//{
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	int ch = fgetc(pf);
//	printf("%c\n", ch);//a
//
//	fseek(pf,4,SEEK_SET);//e
//
//	ch = fgetc(pf);
//	printf("%c\n", ch);//e
//
//	rewind(pf);
//
//	ch = fgetc(pf);
//	printf("%c\n", ch);//a
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

/****4.⽂件读取结束的判定****/
//feof函数检测文件读取是否遇到文件末尾 标志1/0

//ferror函数检测发生错误读取结束	   标志1/0

//例子
#include <stdlib.h>
//int main(void)
//{
//	int c; // 注意：int，⾮char，要求处理EOF
//	FILE* fp = fopen("data.txt", "r");
//	if (!fp) {
//		perror("File opening failed");
//		return EXIT_FAILURE;
//	}
//	//fgetc 当读取失败的时候或者遇到⽂件结束的时候，都会返回EOF
//	while ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环
//	{
//		putchar(c);
//	}
//	//判断是什么原因结束的
//	if (ferror(fp))
//		puts("\nI/O error when reading");
//	else if (feof(fp))
//		puts("\nEnd of file reached successfully");
//	fclose(fp);
//}

#include <stdio.h>

enum { SIZE = 5 };

int main(void)
{
	double a[SIZE] = { 1.,2.,3.,4.,5. };
	FILE* fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式
	fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组
	fclose(fp);
	double b[SIZE];
	fp = fopen("test.bin", "rb");
	size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组
	if (ret_code == SIZE) 
	{
		puts("Array read successfully, contents: ");
		for (int n = 0; n < SIZE; ++n)
			printf("%f ", b[n]);
		putchar('\n');
	}
	else 
	{ // error handling
		if (feof(fp))
			printf("Error reading test.bin: unexpected end of file\n");
		else if (ferror(fp)) 
		{
			perror("Error reading test.bin");
		}
	}
	fclose(fp);
}






